﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace WriteBugs.Library.Utils
{
    public class ConvertHelper
    {
        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="data"></param>
        /// <param name="bFormat">如果为True就加入空格</param>
        /// <returns></returns>
        public static string ByteArrayToHexString(byte[] data, bool bFormat = true)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
            {
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
            }
            string strResult = sb.ToString().Trim().ToUpper();
            if (!bFormat)
            {
                strResult = strResult.Replace(" ", "");
            }

            return strResult;
        }



        /// <summary>
        /// Byte数组转为Double数组
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static double[] TwoByteToDoubleArray(byte[] data)
        {
            List<double> DQ = new List<double>();
            for (int i = 0; i < data.Length / 2; i++)
            {
                byte[] r = new byte[2];
                Array.Copy(data, i * 2, r, 0, 2);
                short s = BitConverter.ToInt16(r, 0);
                DQ.Add(s);
            }
            return DQ.ToArray();
        }

        /// <summary>
        /// 16进制字符串转字节数组
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
            {
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            }
            return buffer;
        }



        /// <summary>
        /// 将对象转换为byte数组(对象转2进制)
        /// </summary>
        /// <param name="obj">被转换对象</param>
        /// <returns>转换后byte数组</returns>
        public static byte[] Object2Bytes(object obj)
        {
            if (obj == null)
                return null;
            byte[] buff;
            using (MemoryStream ms = new MemoryStream())
            {
                IFormatter iFormatter = new BinaryFormatter();
                iFormatter.Serialize(ms, obj);
                buff = ms.GetBuffer();
            }
            return buff;
        }

        /// <summary>
        /// 将byte数组转换成对象 2进制转对象
        /// </summary>
        /// <param name="buff">被转换byte数组</param>
        /// <returns>转换完成后的对象</returns>
        public static object Bytes2Object(byte[] buff)
        {
            if (buff == null)
                return null;
            object obj;
            using (MemoryStream ms = new MemoryStream(buff))
            {
                IFormatter iFormatter = new BinaryFormatter();
                obj = iFormatter.Deserialize(ms);
            }
            return obj;
        }

        /// <summary>
        /// 矩形数组转交错数组(二维)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static T[][] RectangularToArray<T>(T[,] data)
        {

            T[][] returnData = new T[data.GetLength(0)][];
            for (int i = 0; i < data.GetLength(0); i++)
            {
                returnData[i] = new T[data.GetLength(1)];
                for (int j = 0; j < data.GetLength(1); j++)
                {
                    returnData[i][j] = data[i, j];
                }
            }
            return returnData;
        }



        /// <summary>
        /// 获取特征值X轴位置集合
        /// </summary>
        /// <param name="binning"></param>
        /// <returns></returns>
        public static List<int> GetLoctionX(string binning)
        {
            List<int> loctionXs = new List<int>();
            int[] bins = Array.ConvertAll<string, int>(binning.Split(','), s => int.Parse(s));
            int xValue = 0;
            foreach (var bin in bins)
            {
                if (bin < 128)
                {
                    xValue += bin;
                    loctionXs.Add(xValue);
                }
                else
                {
                    xValue += (bin - 128);
                }
            }
            return loctionXs;
        }

        public static T[,] GetTwoDArraybyOne<T>(T[] inArray, int r, int c)
        {
            T[,] outArray = new T[r, c];
            for (int i = 0; i < inArray.Length; i++)
                outArray[i / c, i % c] = inArray[i];
            return outArray;
        }

        /// <summary>
        /// 16进制字符串转字节数组
        /// </summary>
        /// <param name="s"></param>
        /// <param name="reverse">是否倒置</param>
        /// <returns></returns>
        public static byte[] HexToByte(string s, bool reverse = false)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            if (reverse)
            {
                Array.Reverse(buffer);
            }
            return buffer;
        }

        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="data"></param>
        /// <param name="bFormat">true 空 false 无</param>
        /// <returns></returns>
        public static string ByteToHex(byte[] data, bool bFormat)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
            string strResult = sb.ToString().Trim().ToUpper();
            if (!bFormat) strResult = strResult.Replace(" ", "");
            return strResult;
        }

        /// <summary>
        ///    复制数组
        /// </summary>
        /// <param name="sourceArray"></param>
        /// <param name="sourceIndex"></param>
        /// <param name="length"></param>
        /// <param name="destinationArray"></param>
        public static byte[] CopyTo(Array sourceArray, int sourceIndex, int length)
        {
            byte[] destinationArray = new byte[length];
            try
            {
                Array.Copy(sourceArray, sourceIndex, destinationArray, 0, length);
            }
            catch
            {
                destinationArray = new byte[0];
            }
            return destinationArray;
        }

        /// <summary>
        ///拆分任意数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data">数组</param>
        /// <param name="size">每个数组元素的个数</param>
        /// <returns></returns>
        public static List<T[]> SplitArray<T>(T[] data, int size)
        {
            List<T[]> list = new List<T[]>();
            for (int i = 0; i < data.Length / size; i++)
            {
                T[] r = new T[size];
                Array.Copy(data, i * size, r, 0, size);
                list.Add(r);
            }
            if (data.Length % size != 0)
            {
                T[] r = new T[data.Length % size];
                Array.Copy(data, data.Length - data.Length % size, r, 0, data.Length % size);
                list.Add(r);
            }
            return list;
        }

        #region 压缩byte[]
        /// <summary>
        /// 压缩字节数组
        /// </summary>
        /// <param name="str"></param>
        public static byte[] Compress(byte[] inputBytes)
        {
            if (inputBytes == null) return null;
            using (MemoryStream outStream = new MemoryStream())
            {
                using (GZipStream zipStream = new GZipStream(outStream, CompressionMode.Compress, true))
                {
                    zipStream.Write(inputBytes, 0, inputBytes.Length);
                    zipStream.Close(); //很重要，必须关闭，否则无法正确解压
                    return outStream.ToArray();
                }
            }
        }

        /// <summary>
        /// 解压缩字节数组
        /// </summary>
        /// <param name="str"></param>
        public static byte[] Decompress(byte[] inputBytes)
        {
            if (inputBytes == null) return null;
            using (MemoryStream inputStream = new MemoryStream(inputBytes))
            {
                using (MemoryStream outStream = new MemoryStream())
                {
                    using (GZipStream zipStream = new GZipStream(inputStream, CompressionMode.Decompress))
                    {
                        zipStream.CopyTo(outStream);
                        zipStream.Close();
                        return outStream.ToArray();
                    }
                }

            }
        }
        #endregion

        /// <summary>
        /// 获取对象转字节并压缩后的数据
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static byte[] GetCompressedByte(object obj)
        {
            return Compress(Object2Bytes(obj));
        }

        /// <summary>
        /// 获取解压后的字节转对象
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static object GetDecompressedObject(byte[] bytes)
        {
            return Bytes2Object(Decompress(bytes));
        }

        /// <summary>
        /// BASE64 解密
        /// </summary>
        /// <param name="source">待解密字段</param>
        /// <returns></returns>
        public static string UnBase64(string source)
        {
            var btArray = Convert.FromBase64String(source);
            return Encoding.UTF8.GetString(btArray);
        }
    }
}
